-module(edrp_misc).

-export([read_conf/0,
         read_conf/1,
         read_servers/0,
         read_listen_addr/0,
         read_acceptors/0]).

-include("edrp_server.hrl").
-include("edrp_acceptors.hrl").

-define(DEFAULT_CONF, "./priv/edrp.conf").
-define(TAB_NAME, edrp_config).

% read servers from the config file
read_servers() ->
    case get(servers) of
        undefined -> 
            case read_conf() of
                ok -> read_servers();
                {error, Reason} -> {error, Reason}
            end;
        unconfigured ->
            {error, unconfigured};
        {ServerList, Length} ->
            {ok, ServerList, Length}
    end.

% read listen ip and port from the config file
read_listen_addr() ->
    case get(listen_addr) of
        undefined-> 
            case read_conf() of 
                ok -> read_listen_addr();
                {error, Reason} -> {error, Reason}
            end;
        unconfigured ->
            {error, unconfigured};
        {Ip, Port} ->
            {ok, Ip, Port}
    end.

% read acceptors from the config file
read_acceptors() ->
    case get(acceptors) of
        undefined ->
            case read_conf() of
                ok -> read_acceptors();
                {error, Reason} -> {error, Reason}
            end;
        unconfigured ->
            {error, unconfigured};
        Acceptors ->
            {ok, Acceptors}
    end.

% read the default config file
read_conf() -> 
    read_conf(?DEFAULT_CONF).

% read config from the ConfigFile
read_conf(ConfigFile) when is_list(ConfigFile) ->
    case file:consult(ConfigFile) of
        {ok, ConfigData} ->
            try
                put(servers, unconfigured),
                put(listen_addr, unconfigured),
                put(acceptors, unconfigured),
                check_terms(ConfigData)
            catch 
                error: Reason ->
                    {error, Reason}
            end;
        {error, Reason} ->
            {error, Reason}
    end.   
    
check_terms(ConfigData) when is_list(ConfigData) ->
    lists:foreach(fun check_term/1, ConfigData).

check_term({servers, ServerList}) when is_list(ServerList) ->
    Servers = lists:foldl(fun check_server/2, {[], 0}, ServerList),
    put(servers, Servers);
check_term({listen_addr, ip, Ip, port, Port}) 
    when is_tuple(Ip), is_integer(Port) ->
    put(listen_addr, {Ip, Port});
check_term({acceptors, limit, Limit, start, Start, minspare, Minspare,
            maxspare, Maxspare, maxreq, Maxreq}) 
    when is_integer(Limit), is_integer(Start), is_integer(Minspare),
         is_integer(Maxspare), is_integer(Maxreq) ->
    put(acceptors, #acceptors{limit    = Limit,
                              start    = Start,
                              minspare = Minspare,
                              maxspare = Maxspare,
                              maxreq   = Maxreq}).

check_server({server, ip, Ip, port, Port}, {ServerList,Length}) 
    when is_tuple(Ip), is_integer(Port) ->
    Addr = #addr{ip=Ip, port=Port},
    case lists:keymember(Addr, 2, ServerList) of
        true -> 
            {ServerList, Length};
        false ->
            Server = #server{addr=Addr, load=0, weight=?DEFAULT_WEIGHT},
            {[Server|ServerList], Length+1}
    end;
check_server({server,ip,Ip,port,Port,weight,Weight}, {ServerList,Length}) 
    when is_tuple(Ip), is_integer(Port), is_integer(Weight),
         Weight >= ?MIN_WEIGHT, Weight =< ?MAX_WEIGHT ->
    Addr = #addr{ip=Ip, port=Port},
    case lists:keymember(Addr, 2, ServerList) of
        true -> 
            {ServerList, Length};
        false ->
            Server = #server{addr=Addr, load=0, weight=Weight},
            {[Server|ServerList], Length+1}
    end.
